package com.project.modules.oss.cloud;

import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import com.project.common.exception.RRException;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.FileCopyUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 阿里云存储
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-03-26 16:22
 */
public class AliyunUtils extends CloudStorageService {
    private OSSClient client;

    public AliyunUtils(CloudStorageConfig config){
        this.config = config;
        //初始化
        init();
    }

    private void init(){
        // 创建ClientConfiguration实例
        ClientConfiguration conf = new ClientConfiguration();
        // 设置HTTP最大连接数为512
        conf.setMaxConnections(512);
        // 设置TCP连接超时为5000毫秒
        conf.setConnectionTimeout(5000);
        // 设置最大的重试次数为3
        conf.setMaxErrorRetry(3);
        // 设置Socket传输数据超时的时间为2000毫秒
        conf.setSocketTimeout(2000);
        //初始化OSSClient客户端

        client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(),
                config.getAliyunAccessKeySecret(),conf);
    }

    @Override
    public String upload(byte[] data, String path) {
        return upload(new ByteArrayInputStream(data), path);
//        return multipartUpload(new ByteArrayInputStream(data), path);
    }

    /**
     * 普通上传文件
     * @param inputStream   字节流
     * @param path          文件路径，包含文件名
     * @return 文件路径
     */
    @Override
    public String upload(InputStream inputStream, String path) {
        try {
            client.putObject(config.getAliyunBucketName(), path, inputStream);
        } catch (Exception e){
            throw new RRException("上传文件失败，请检查配置信息", e);
        }

        return config.getAliyunDomain() + "/" + path;
    }

    @Override
    public byte[] download(String filepath) throws IOException {
        if(StringUtils.isBlank(filepath)){
            return null ;
        }
        //构建文件下载路径
        try {
            OSSObject object = client.getObject(config.getAliyunBucketName(), filepath);
            //验证是否查询到了文件 如果未查询到 则直接返回空
            if(object==null){
                return null;
            }
            // 获取Object的输入流
            InputStream objectContent = object.getObjectContent() ;
            return FileCopyUtils.copyToByteArray(objectContent) ;
        } catch (Exception e) {
            return null;
        }
    }

    public String multipartUpload (InputStream inputStream, String path) {

        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(config.getAliyunBucketName(), path);
        InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
        String uploadId = result.getUploadId();

        List<PartETag> partETags = new ArrayList<PartETag>();
        UploadPartRequest uploadPartRequest = new UploadPartRequest();
        uploadPartRequest.setBucketName(config.getAliyunBucketName());
        uploadPartRequest.setKey(path);
        uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setInputStream(inputStream);
        // 设置分片大小，除最后一个分片外，其它分片要大于100KB
        uploadPartRequest.setPartSize(100 * 1024);
        // 设置分片号，范围是1~10000，
        uploadPartRequest.setPartNumber(1);
        UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
        partETags.add(uploadPartResult.getPartETag());

        Collections.sort(partETags, new Comparator<PartETag>() {
            @Override
            public int compare(PartETag p1, PartETag p2) {
                return p1.getPartNumber() - p2.getPartNumber();
            }
        });
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(config.getAliyunBucketName(), path, uploadId, partETags);
        client.completeMultipartUpload(completeMultipartUploadRequest);

        return config.getAliyunDomain() + "/" + path;
    }

    /**
     * 断点续传
     * @param fileName 文件名
     * @return
     */
    public String checkpointUpload (String fileName, String path) {
        try {
            // 设置断点续传请求
            UploadFileRequest uploadFileRequest = new UploadFileRequest(config.getAliyunBucketName(),path);
            // 指定上传的本地文件
            uploadFileRequest.setUploadFile(fileName);
            // 指定上传并发线程数
            uploadFileRequest.setTaskNum(5);
            // 指定上传的分片大小
            uploadFileRequest.setPartSize(1 * 1024 * 1024);
            // 开启断点续传
            uploadFileRequest.setEnableCheckpoint(true);
            // 断点续传上传
            client.uploadFile(uploadFileRequest);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        return config.getAliyunDomain() + "/" + path;
    }

    @Override
    public String uploadSuffix(byte[] data, String suffix) {
        return upload(data, getPath(config.getAliyunPrefix(), suffix));
    }

    @Override
    public String uploadSuffix(InputStream inputStream, String suffix) {
        return upload(inputStream, getPath(config.getAliyunPrefix(), suffix));
    }
}
